#include "AngleSpaceTransformer.h"


AngleSpaceTransformer::AngleSpaceTransformer(AngleSpace* _as, MItMeshPolygon* faceIt, MItMeshVertex* vertsIt, Options* opts, MFnMesh* mesh)
{
	as = _as;
	map<int, VertexBase*> allVerts = as->getVertexMap();
	map<int, TriangleBase*> allTris = as->getTriangleMap();
	map<int,EdgeBase*> allEdges = as->getEdgeMap();

	queue<EdgeBase::queueElement>* fixingQueue = new queue<EdgeBase::queueElement>();
	
	EdgeBase::queueElement first;
	TriangleBase* tri = allTris[0];
	EdgeBase* firstEdge = tri->getABEdge();
	first.edge = firstEdge;
	first.tri = tri;
	first.start = firstEdge->getStart();
	first.end = firstEdge->getEnd();
	TriangleBase* otherTri = firstEdge->getNextTriangle(tri);
	if(otherTri != NULL)
	{
		first.start->setUVPoint(0.0, 0.0, otherTri);
		first.end->setUVPoint(1.0, 0.0, otherTri);
	}
	else
	{
		first.start->setUVPoint(0.0, 0.0, tri);
		first.end->setUVPoint(1.0, 0.0, tri);
	}

	fixingQueue->push(first);

	while(!fixingQueue->empty())	
	{
		EdgeBase::queueElement current = fixingQueue->front();
		fixingQueue->pop();
		current.edge->fixOppositeVertices(fixingQueue, current.tri, current.start, current.end);		
	}
	delete fixingQueue;


	MIntArray uvCounts(allTris.size(), 3);
	MIntArray uvIds(allTris.size()*3);
	MFloatArray uArray(allTris.size()*3);
	MFloatArray vArray(allTris.size()*3);
	
	int i=0;
	faceIt->reset();
	while(!faceIt->isDone())
	{
		TriangleBase* tri = allTris[faceIt->index()];
		MIntArray vertIndicesInOrder;
		faceIt->getVertices(vertIndicesInOrder);
		VertexBase* A = allVerts[vertIndicesInOrder[0]];
		VertexBase* B = allVerts[vertIndicesInOrder[1]];
		VertexBase* C = allVerts[vertIndicesInOrder[2]];		
		
		uArray[i] = A->getUVPoint(tri).u;
		vArray[i] = A->getUVPoint(tri).v;
		uvIds[i] = i;
		i++;
		uArray[i] = B->getUVPoint(tri).u;
		vArray[i] = B->getUVPoint(tri).v;
		uvIds[i] = i;
		i++;
		uArray[i] = C->getUVPoint(tri).u;		
		vArray[i] = C->getUVPoint(tri).v;
		uvIds[i] = i;
		i++;
		faceIt->next();
	}

	double maxu = -100000;
	double minu = 100000;
	double maxv = -100000;
	double minv = 100000;
	

	for(int i=0; i<uArray.length(); i++)
	{
		if(uArray[i] > maxu)
			maxu = uArray[i];
		if(uArray[i] < minu)
			minu = uArray[i];
		if(vArray[i] > maxv)
			maxv = vArray[i];
		if(vArray[i] < minv)
			minv = vArray[i];
	}

	double diffu = maxu - minu;
	double diffv = maxv - minv;
	double scaling = 1;
	if(diffu > diffv)	
		scaling = 1/diffu;	
	else
		scaling = 1/diffv;	

	for(int i=0; i<uArray.length(); i++)
	{
		uArray[i] += abs(minu);
		vArray[i] += abs(minv);	
		
		uArray[i] *= -scaling;
		vArray[i] *= scaling;

		uArray[i] += abs(diffu)*scaling;
	}

	MString name = opts->mapName.c_str();
	mesh->clearUVs(&name);
	mesh->createUVSetWithName(name);	
	mesh->numUVs();
	mesh->setUVs(uArray, vArray, &name);
	mesh->assignUVs(uvCounts, uvIds, &name);


//	checkMatchesOutput(as, faceIt, vertsIt, opts, mesh);


}

void AngleSpaceTransformer::checkMatchesOutput(AngleSpace* as, MItMeshPolygon* faceIt, MItMeshVertex* vertsIt, Options* opts, MFnMesh* mesh)
{
	map<int, VertexBase*> allVerts = as->getVertexMap();
	map<int, TriangleBase*> allTris = as->getTriangleMap();
	map<int,EdgeBase*> allEdges = as->getEdgeMap();

	//faceIt->reset();
	//while(!faceIt->isDone())
	//{
	//	TriangleBase* tri = allTris[faceIt->index()];
	//	MIntArray vertIndicesInOrder;
	//	faceIt->getVertices(vertIndicesInOrder);
	//	VertexBase* A = allVerts[vertIndicesInOrder[0]];
	//	VertexBase* B = allVerts[vertIndicesInOrder[1]];
	//	VertexBase* C = allVerts[vertIndicesInOrder[2]];		
	//	
	//	uArray[i] = A->getUVPoint(tri).u;
	//	vArray[i] = A->getUVPoint(tri).v;
	//	uvIds[i] = i;
	//	i++;
	//	uArray[i] = B->getUVPoint(tri).u;
	//	vArray[i] = B->getUVPoint(tri).v;
	//	uvIds[i] = i;
	//	i++;
	//	uArray[i] = C->getUVPoint(tri).u;		
	//	vArray[i] = C->getUVPoint(tri).v;
	//	uvIds[i] = i;
	//	i++;
	//	faceIt->next();
	//}
}

AngleSpaceTransformer::~AngleSpaceTransformer(void)
{
}
